import { computed, reactive, toRefs, watch } from 'vue'
import http from '../http'
import { chunk, debounce, flattenDeep, get, isEmpty, pick } from 'lodash'

export interface PageReqKeys {
  'page-size': string
  'current-page': string
  total: string
  'page-sizes': string
}

export interface PageResKeys {
  list: string
  total: string
}

export interface FilterKeys {
  // 前端搜索时，需要确定列表中的哪些字段进行搜索
  keywords?: string[] // 模糊搜索
  single?: string[] // 其他搜索
}
export interface PageDefaultProps {
  filterKeys?: FilterKeys
  getUrl?: () => PageDefaultProps['url']
  getData?: () => void
  url?: string // table请求url
  method?: string // 请求方式
  pageReqKeys: PageReqKeys // page请求Keys
  pageResKeys: PageResKeys
  reqParams: Record<string, unknown> // 请求时除了page相关的其他参数
  queryWatch: boolean
}

export interface PageProps extends Partial<PageDefaultProps> {
  url?: string
}

export interface PageState {
  page: Record<string, any>
  list: unknown[]
  // filterList: unknown[] // 前端搜索后的列表、
}

const defaultProps = {
  queryWatch: false,
  method: 'POST',
  url: '',
  filterKeys: {
    keywords: ['name']
  },
  pageReqKeys: {
    'page-size': 'limit',
    'current-page': 'page',
    total: 'count',
    'page-sizes': 'page-sizes'
  },
  pageResKeys: {
    list: 'list',
    total: 'count'
  },
  reqParams: {}
}

export default (params: PageProps) => {
  const props: PageDefaultProps = { ...defaultProps, ...params }
  const { url, pageReqKeys, pageResKeys, reqParams, getData, filterKeys, getUrl, method } = props
  const state: PageState = reactive({
    page: {
      [pageReqKeys['page-size']]: 10,
      [pageReqKeys['current-page']]: 1,
      [pageReqKeys['total']]: 0,
      [pageReqKeys['page-sizes']]: [5, 10, 30]
    },
    list: []
  })

  const pagesData: any = computed(() => {
    const list: any = getData?.()
    if (isEmpty(list)) {
      return list
    }
    return chunk(
      list?.filter((i: any) => !isEmpty(i)),
      state.page[pageReqKeys['page-size']]
    )
  })

  const paramHasVal = () => Object.values(reqParams).some((i: any) => !isEmpty(i))

  const dataFilter = () => {
    state.page[pageReqKeys['current-page']] = 1
    const list: any = getData?.()
    const { keywords = [], single = [] } = filterKeys as any
    const filterList = list
      .filter((i: any) => keywords.some((m: any) => (String(i[m]) || '').includes((reqParams as any).keywords)))
      .filter((i: any) => single.some((m: any) => i[m] === reqParams[m] || reqParams[m] === ''))
    const chunkList = chunk(
      filterList?.filter((i: any) => !isEmpty(i)),
      state.page[pageReqKeys['page-size']]
    )
    state.list = flattenDeep(chunkList.filter((_: any, m: number) => m + 1 === 1))
    state.page.total = filterList.length
  }

  const frontEndPaging = (page?: number) => {
    if (paramHasVal()) {
      return dataFilter()
    }
    const cmpPage = page || pick(state.page, [pageReqKeys['current-page']]).page
    state.list = flattenDeep(pagesData.value.filter((_: any, m: number) => m + 1 === cmpPage))
    state.page.total = (getData?.() as any)?.length
    const curPage = state.page[pageReqKeys['current-page']]
    if (curPage > 1 && state.list.length === 0) {
      state.page[pageReqKeys['current-page']] -= 1
      frontEndPaging()
    }
  }

  const onPageChange = debounce(async (page?: number) => {
    if (typeof page === 'number') {
      state.page[pageReqKeys['current-page']] = page
    }
    if (getData) {
      return frontEndPaging(page)
    }
    let cmpUrl = url
    if (!cmpUrl) {
      cmpUrl = getUrl?.()
    }
    if (!cmpUrl) {
      return
    }
    const cmpMethod = method === 'POST' ? 'data' : 'params'
    try {
      const res = await http({
        url: cmpUrl,
        method,
        [cmpMethod]: {
          ...pick(state.page, [pageReqKeys['current-page'], pageReqKeys['page-size']]),
          ...reqParams
        }
      })
      state.list = get(res, pageResKeys['list'])
      state.page.total = get(res, pageResKeys['total'])
      const curPage = state.page[pageReqKeys['current-page']]
      if (curPage > 1 && state.list.length === 0) {
        state.page[pageReqKeys['current-page']] -= 1
        await onPageChange()
      }
    } catch (error) {
      console.log(error)
    }
  })

  const onPageSizeChange = (size: number) => {
    state.page[pageReqKeys['page-size']] = size
    onPageChange()
  }

  watch(
    reqParams,
    () => {
      props.queryWatch && onPageChange()
    },
    {
      immediate: true,
      deep: true
    }
  )

  if (!Object.keys(reqParams).length) {
    props.queryWatch && onPageChange()
  }

  return {
    onPageChange,
    onPageSizeChange,
    ...toRefs(state)
  }
}
